/*
 * OpenParts
 * A dynamic-loading components framework for GWT
 * Copyright (C) 2011 Christophe Bouthier  [chris{AT}binary-gastronome{DOT}fr]
 *
 * This work is partially based on work I have done at INRIA (http://www.inria.fr) 
 * in the context of the Qualipso European Project (http://qualipso.org/),
 * The work done at INRIA is Copyright (C) 2006-2011 INRIA
 *
 * This work is distributed under the LGPL version 3
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3
 * as published by the Free Software Foundation. See the GNU
 * Lesser General Public License in LGPL.txt for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package fr.openparts.OpenParts.client;

import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * OPSlot class is used by container view to embed the view of another component. It contains a {@link OPViewProxy} that represent a proxy to the view embedded
 * in this slot. This proxy allows the container view to dispatch message to the embedded view, and to manipulate it like it was a real view in the same widget
 * tree. It also allows to register handlers that will be called if the embedded view dispatch message to this container slot.
 * 
 * @author Christophe Bouthier [chris{AT}binary-gastronome{DOT}fr]
 * @creation.date 11 July 2010
 */
public class OPSlot extends SimplePanel {

    /**
     *  Slot id for this slot
     */
    protected String slotId;

    /**
     * Proxy for the view embedded in this slot
     */
    protected OPViewProxy viewProxy;

    /**
     * Constructor, taking the slot id as parameter.
     * 
     * @param slotId
     *            the id of this slot. Shouldn't be null. Shouldn't be empty.
     */
    public OPSlot(final String slotId) {
        super();

        assert slotId != null : "parameter slotId shouldn't be null";
        assert !slotId.isEmpty() : "parameter slotId shouldn't be empty";

        this.slotId = slotId;
        getElement().setId(slotId);

        viewProxy = new OPViewProxy(slotId);

        createAndRegisterDispatcher();
    }

    /**
     * Returns the slot id of this slot.
     * 
     * @return the slot id. Cannot be null.
     */
    public String getSlotId() {
        return slotId;
    }

    /**
     * Returns the proxy of the embedded view. This is never null, even if there is no view embedded yet. To test if there is a view really embedded, call
     * {@link OPViewProxy#isProxyAttachedToRealView()} on the proxy.
     * 
     * @return the proxy for the embedded view. Cannot be null, even if there is no view really embedded yet.
     */
    public OPViewProxy getViewProxy() {
        return viewProxy;
    }

    /**
     * Create an {@link OPMessagesDispatcher}, register it with the element of this slot id, and register the view proxy on it.
     */
    protected void createAndRegisterDispatcher() {
        final OPMessagesDispatcher dispatcher = OPMessagesDispatcher.dispatcherFactory(slotId);

        dispatcher.attachDispatcherOnElement(getElement());
        dispatcher.registerViewProxy(viewProxy);
    }

    /**
     * Add a widget displayed until a view is attached to the slot. Used to display a "loading..." message while the view is loading. The widget is
     * automatically removed when the view is attached. Don't do anything if there is already a view attached to this slot.
     * 
     * @see com.google.gwt.user.client.ui.SimplePanel#add(com.google.gwt.user.client.ui.Widget)
     * 
     * @param child
     *            the widget to add. Shouldn't be null.
     */
    @Override
    public void add(final Widget child) {
        assert child != null : "parameter child shouldn't be null";

        if (viewProxy.isProxyAttachedToRealView()) {
            return;
        }
        
        super.add(child);
    }

}
